﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Percolation.Gui
{
    public partial class EditPackForm : Form
    {
        public EditPackForm(NetPackSettings packSettings)
        {
            m_packSettings = packSettings;
            InitializeComponent();
            InitializeList();
        }

        protected NetPackSettings m_packSettings;

        protected void InitializeList()
        {
            foreach (NetTypeEnum netType in System.Enum.GetValues(typeof(NetTypeEnum)))
                m_packTypeComboBox.Items.Add(EnumUtils.GetString(netType));

            m_packTypeComboBox.SelectedIndex = (int) m_packSettings.NetType;
        }

        protected void updatePage()
        {

            if (m_packSettings.NetType == NetTypeEnum.Random || m_packSettings.NetType == NetTypeEnum.VerGradient || m_packSettings.NetType == NetTypeEnum.HorGradient)
            {
                m_expCountTextBox.Text = m_packSettings.Count.ToString();
                m_probability0TextBox.Text = m_packSettings.Probability0.ToString();
            }
            else
            {
                m_expCountTextBox.Text = "10";
                m_probability0TextBox.Text = "0.5";
            }

            if (m_packSettings.NetType == NetTypeEnum.VerGradient || m_packSettings.NetType == NetTypeEnum.HorGradient)
                m_probability1TextBox.Text = m_packSettings.Probability1.ToString();
            else
                m_probability1TextBox.Text = "0.5";

            m_widthTextBox.Text = m_packSettings.Width.ToString();
            m_heightTextBox.Text = m_packSettings.Height.ToString();
        }

        protected void updateProperties()
        {
            m_packSettings.NetType = (NetTypeEnum)m_packTypeComboBox.SelectedIndex;

            if (m_packSettings.NetType == NetTypeEnum.Random || m_packSettings.NetType == NetTypeEnum.VerGradient || m_packSettings.NetType == NetTypeEnum.HorGradient)
            {
                m_packSettings.Count = System.Convert.ToInt32(m_expCountTextBox.Text);
                m_packSettings.Probability0 = System.Convert.ToDouble(m_probability0TextBox.Text);
            }

            if (m_packSettings.NetType == NetTypeEnum.VerGradient || m_packSettings.NetType == NetTypeEnum.HorGradient)
                m_packSettings.Probability1 = System.Convert.ToDouble(m_probability1TextBox.Text);
        }

        private bool isValidProbability(double probability)
        {
            return (0 <= probability && probability <= 1.0);
        }

        private bool isValidExpCount(int expCount)
        {
            return (1 <= expCount && expCount <= 1000);
        }

        private bool isValidGradProbability(double gradProbability)
        {
            if (validateProbability())
            {
                double probability = System.Convert.ToDouble(m_probability0TextBox.Text);
                return isValidProbability(probability - probability * gradProbability) && isValidProbability(probability + probability * gradProbability);
            }

            return false;
        }

        private bool validateProbability()
        {
            if (m_probability0TextBox.Visible == false)
                return true;

            try
            {
                double probability = System.Convert.ToDouble(m_probability0TextBox.Text);
                if (isValidProbability(probability))
                {
                    m_errorProvider.SetError(m_probability0TextBox, "");
                    return true;
                }

                m_errorProvider.SetError(m_probability0TextBox, "Probability value is invalid (should be greater or equal than 0 and less or equal than 1)");
                return false;
            }
            catch (Exception)
            {
                m_errorProvider.SetError(m_probability0TextBox, "You entered some non-digit symbols");
                return false;
            }
        }

        private bool validateGradProbability()
        {
            if (m_probability1TextBox.Visible == false)
                return true;

            try
            {
                double gradProbability = System.Convert.ToDouble(m_probability1TextBox.Text);
                if (isValidGradProbability(gradProbability))
                {
                    m_errorProvider.SetError(m_probability1TextBox, "");
                    return true;
                }

                m_errorProvider.SetError(m_probability1TextBox, "Gradient probability value is invalid with this parameter of average probability");
                return false;
            }
            catch (Exception)
            {
                m_errorProvider.SetError(m_probability1TextBox, "You entered some non-digit symbols");
                return false;
            }
        }

        private bool validateExpCount()
        {
            if (m_expCountTextBox.Visible == false)
                return true;

            try
            {
                int expCount = System.Convert.ToInt32(m_expCountTextBox.Text);
                if (isValidExpCount(expCount))
                {
                    m_errorProvider.SetError(m_expCountTextBox, "");
                    return true;
                }

                m_errorProvider.SetError(m_expCountTextBox, "Experiments count value is invalid (should be greater or equal than 1 and less or equal than 1000)");
                return false;
            }
            catch (Exception)
            {
                m_errorProvider.SetError(m_expCountTextBox, "You entered some non-digit symbols");
                return false;
            }
        }

        private bool validateForm()
        {
            bool valid = true;
            valid &= validateProbability();
            valid &= validateExpCount();
            valid &= validateGradProbability();
            return valid;
        }

        private void okButton_Click(object sender, EventArgs e)
        {
            if (!validateForm())
                return;

            updateProperties();

            DialogResult = System.Windows.Forms.DialogResult.OK;
            Close();
        }

        private void cancelButton_Click(object sender, EventArgs e)
        {
            DialogResult = System.Windows.Forms.DialogResult.Cancel;
            Close();
        }

        private void updateAccessibleState(bool expCountField, bool probability0Field, bool probability1Field)
        {
            m_expCountLabel.Visible = expCountField;
            m_expCountTextBox.Visible = expCountField;
            m_probability0Label.Visible = probability0Field;
            m_probability0TextBox.Visible = probability0Field;
            m_probability1Label.Visible = probability1Field;
            m_probability1TextBox.Visible = probability1Field;
        }

        private void packTypeComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (m_packTypeComboBox.SelectedIndex == (int)NetTypeEnum.VerGradient
                || m_packTypeComboBox.SelectedIndex == (int)NetTypeEnum.HorGradient)
                updateAccessibleState(true, true, true);
            else if (m_packTypeComboBox.SelectedIndex == (int)NetTypeEnum.Random)
                updateAccessibleState(true, true, false);
            else
                updateAccessibleState(false, false, false);
        }

        private void EditPackForm_Load(object sender, EventArgs e)
        {
            updatePage();
        }
    }
}
